package com.example.repeatsubmitdemo.repeatSubmit.aspect;

import cn.hutool.log.StaticLog;
import com.example.repeatsubmitdemo.repeatSubmit.RepeatSubmit;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.concurrent.TimeUnit;

/**
 * @author tianzhuang
 * @version 1.0
 * @date 2022/1/11 14:16
 */
@Aspect
@Slf4j
@Component
public class RepeatSubmitAspect {
    @Resource
    private RedisTemplate<String, Object> redisTemplate;


    @Pointcut("@annotation(com.example.repeatsubmitdemo.repeatSubmit.RepeatSubmit) || @within(com.example.repeatsubmitdemo.repeatSubmit.RepeatSubmit)")
    public void pointCut(){}


    @Around("pointCut()")
    private Object around(ProceedingJoinPoint point) {
        RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
        //从获取RequestAttributes中获取HttpServletRequest的信息
        HttpServletRequest request = (HttpServletRequest) requestAttributes.resolveReference(RequestAttributes.REFERENCE_REQUEST);
        try {
            // 获取当前用户的token
            StaticLog.info("检测是否重复提交");
            // 获取url
            String requestURI = request.getRemoteHost();
            // 获取当前请求的方法名
            MethodSignature signature = (MethodSignature) point.getSignature();
            Method method = signature.getMethod();
            String name = method.getName();
            StringBuilder key = new StringBuilder();
            key.append(requestURI).append(name);
            if (redisTemplate.hasKey(String.valueOf(key))) {
                log.error("监测到重复提交>>>>>>>>>>method:{}======url:{}", name, requestURI);
                return "重复提交";
            }
            // 获取注解
            RepeatSubmit annotation = method.getAnnotation(RepeatSubmit.class);
            Long timeout = annotation.interval();
            // 此处我用token和请求方法名为key存入redis中，有效期为timeout 时间， 也可以使用ip地址做为key
            redisTemplate.opsForValue().set(String.valueOf(key), requestURI, timeout, TimeUnit.SECONDS);
            return point.proceed();
        } catch (Throwable throwable) {
            StaticLog.error("=====>>>>>>操作失败：{}", throwable);
            return "操作失败";
        }
    }
}
